package cn.zk.commom.tcp.obd;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class ObdServerHandler extends SimpleChannelInboundHandler<ObdAnalyse> {
    //    public static ObdAnalyse obdAnalyse;
//
//    @Autowired
//    public void WorkServerHandler(ObdAnalyse obdAnalyse) {
//        ObdServerHandler.obdAnalyse = obdAnalyse;
//    }
    // 一个channel使用一个ObdAnalyse
    public static final ConcurrentHashMap<ChannelId, ObdAnalyse> obdAnalyseMap = new ConcurrentHashMap();

    /**
     * channelAction
     * channel 通道 action 活跃的
     * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //log.info("服务端：" + ctx.channel().localAddress().toString() + " 通道开启！");
        log.info("服务端：" + ctx.channel().remoteAddress().toString() + " 通道开启！");
        ctx.channel().writeAndFlush("连接成功！");
        // 创建ObdAnalyse
        obdAnalyseMap.put(ctx.channel().id(), new ObdAnalyse());
    }

    /**
     * channelInactive
     * channel 通道 Inactive 不活跃的
     * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //log.info("服务端：" + ctx.channel().localAddress().toString() + " 通道关闭！");
        log.info("服务端：" + ctx.channel().remoteAddress().toString() + " 通道关闭！");
        // 删除ObdAnalyse
        obdAnalyseMap.remove(ctx.channel().id());
        // 关闭流
    }

    /**
     * @param buf
     * @return
     * @author Taowd
     * TODO  此处用来处理收到的数据中含有中文的时  出现乱码的问题
     */
    private String getMessage(ByteBuf buf) {
        byte[] con = new byte[buf.readableBytes()];
        buf.readBytes(con);
        try {
            return new String(con, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 功能：读取客户端发送过来的信息 （修改版）
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ObdAnalyse obdAnalyse) throws Exception {
        log.info("开始业务逻辑处理:ip为=>{},channelId=>{},obdAnalyse对象=>{}",
                ctx.channel().remoteAddress(),ctx.channel().id(),obdAnalyse.hashCode());

//        String str1 = "";
//        //打印数据
//        StringBuilder str = obdAnalyse.PrintFrameData();
//        //此处是注册消息，可以进行一些处理
//        byte[] sendData = obdAnalyse.GenerateRegisterMsgSendData();
//        if (null != sendData) {
//            //out.write(sendData);
//            ctx.channel().writeAndFlush(sendData);
//            //打印发送的数据
//            str1 = "";
//            for (int i = 0; i < sendData.length; i++) {
//                str1 += String.format("%02x", sendData[i]);
//            }
//            System.out.println("TCP_Send: = >" + str1);
//            return;
//        }
//        boolean isAuth = obdAnalyse.GenerateAuthenticationMsgSendData();
//        if (!isAuth) {
//            //此处是鉴权消息，可以进行一些处理
//        }
//        //
//        sendData = obdAnalyse.GenerateCommonMsgSendData();
//        if (null != sendData) {
//            ctx.channel().writeAndFlush(sendData);
//            //打印发送的数据
//            str1 = "";
//            for (int i = 0; i < sendData.length; i++) {
//                str1 += String.format("%02x", sendData[i]);
//            }
//            System.out.println("TCP_Send: = >" + str1);
//        }
//        ObdDTO obdDTO = new ObdDTO();
//        //解析成员变量 并打印.
//        System.out.println("============================================开始打印信息============================================");
//        System.out.println("消息ID：" + obdAnalyse.mMsgId + "(0x" + String.format("%04x", obdAnalyse.mMsgId) + ")");
//        System.out.println("总端编号：" + obdAnalyse.mPhoneNumber);
//        System.out.println("消息流水号：" + obdAnalyse.mMsgSerialNumber);
//        log.info("消息流水号:{}", obdAnalyse.mMsgSerialNumber);
//        log.info("obdAnalyse解析数据:{}", obdAnalyse);
//        obdDTO.setMsg_count(obdAnalyse.mMsgSerialNumber);
//        LambdaQueryWrapper<CarDO> query = Wrappers.lambdaQuery();
//        query.eq(CarDO::getOdbCode, obdAnalyse.mPhoneNumber);
//        CarDO carDO = (CarDO) SpringContextHolder.getBean(ICarService.class).getOne(query);
//        RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
//        if (carDO != null) {
//            CarTypeDO carTypeDO = SpringContextHolder.getBean(ICarTypeService.class).getById(carDO.getCarTypeId());
//            DeptDO deptDO = SpringContextHolder.getBean(IDeptService.class).getById(carDO.getDeptId());
//            obdDTO.setCarId(carDO.getCarId());
//            obdDTO.setCarType(carTypeDO.getCarTypeName());
//            obdDTO.setCarNum(carDO.getCarNum());
//            obdDTO.setDeptId(carDO.getDeptId());
//            obdDTO.setDeptName(deptDO.getDeptName());
//            obdDTO.setObdCode(obdAnalyse.mPhoneNumber);
//            obdDTO.setMCurrData(str.toString());
//            // 查询司机
//            Long driverId = SpringContextHolder.getBean(IScheDriverStaffService.class).findDriverId(obdDTO.getCarId(), new Date());
//            if (driverId > 0) {
//                obdDTO.setDriver(SpringContextHolder.getBean(IStaffService.class).getById(driverId).getStaffName());
//                obdDTO.setStaffId(driverId);
//            }
//            // 位置信息
//            if (obdAnalyse.mPosition != null && obdAnalyse.mPosition.size() > 0) {
//                int posSize = obdAnalyse.mPosition.size();
//                if (posSize > 1) {
//                    //System.out.println("--共" + posSize + "条位置信息");
//                    log.info("--共{}条位置信息", posSize);
//                }
//                for (int i = 0; i < posSize; ++i) {
//                    if (posSize > 1) {
//                        //System.out.println("----第" + (i + 1) + "条位置信息");
//                        log.info("----第{}条位置信息", (i + 1));
//                    }
//                    Position _pos = obdAnalyse.mPosition.get(i);
//                    if (_pos.mIsValid) {
//                        Map<String, BigDecimal> lonmap = GouldUtils.convert(new BigDecimal(_pos.mLongitude), new BigDecimal(_pos.mLatitude), "");
//                        obdDTO.setMStateInfo(_pos.mStateInfo);
//                        obdDTO.setMLatitude(lonmap.get("la"));
//                        obdDTO.setMLongitude(lonmap.get("lo"));
//                        obdDTO.setMSpeed(BigDecimal.valueOf(_pos.mSpeed));
//                        obdDTO.setMDirection(BigDecimal.valueOf(_pos.mDirection));
//                        // 时间采用24小时制
//                        obdDTO.setLocTime(DateUtil.parse(String.valueOf(_pos.mTime), "yyMMddHHmmss"));
//                        System.out.println("     |--报警标志:" + _pos.mWarnInfo);
//                        System.out.println("     |--车辆状态:" + _pos.mStateInfo);
//                        System.out.println("     |--纬度:" + _pos.mLatitude);
//                        System.out.println("     |--经度:" + _pos.mLongitude);
//                        System.out.println("     |--海拔:" + _pos.mAltitude);
//                        System.out.println("     |--速度:" + _pos.mSpeed);
//                        System.out.println("     |--方向:" + _pos.mDirection);
//                        System.out.println("     |--时间:" + _pos.mTime);
//                        obdDTO.setAddress(GouldUtils.getAMapByLngAndLat(obdDTO.getMLongitude().toString(), obdDTO.getMLatitude().toString()));
//                    }
//                    //
//                    if (null != _pos.mAddItemBasicData && _pos.mAddItemBasicData.mIsValid) {
//                        PositionItemBasicData baseData = _pos.mAddItemBasicData;
//                        PositionItemCarData positionItemCarData = _pos.mAddItemCarData;
//
//                        if (baseData.mIsMileageValid) {
//                            System.out.println("     |--总里程算法类型:" + baseData.mMileageType);
//                            System.out.println("     |--总里程(米):" + baseData.mMileageValue);
//                            obdDTO.setMMileageValue(baseData.mMileageValue);
//                        }
//                        if (positionItemCarData != null) {
//                            System.out.println("     |--剩余油量类型:" + positionItemCarData.mOilType);
//                            System.out.println("     |--剩余油量:" + positionItemCarData.mRemainingOil);
//                            obdDTO.setMOilType(positionItemCarData.mOilType);
//                            obdDTO.setMRemainingOil(BigDecimal.valueOf(positionItemCarData.mRemainingOil));
//                        }
//                        if (baseData.mIsOilConsumptionValid) {
//                            System.out.println("     |--总耗油量算法类型:" + baseData.mOilConsumptionType);
//                            System.out.println("     |--总耗油量(ml):" + baseData.mOilConsumptionValue);
//                            obdDTO.setMOilConsumptionValue(baseData.mOilConsumptionValue);
//                        }
//                        if (baseData.mIsRunTimeValid) {
//                            System.out.println("     |--总运行时长(秒):" + baseData.mRunTime);
//                            obdDTO.setMRunTime(baseData.mRunTime);
//                        }
//                        if (baseData.mIsFlameOutValid) {
//                            System.out.println("     |--总熄火时长(秒):" + baseData.mFlameOutDuration);
//                            obdDTO.setMFlameOutDuration(baseData.mFlameOutDuration);
//                        }
//                        if (baseData.mIsIdlingTimeValid) {
//                            System.out.println("     |--总怠速时长(秒):" + baseData.mIdlingTime);
//                            obdDTO.setMIdlingTime(baseData.mIdlingTime);
//                        }
//                        if (baseData.mIsAccValid) {
//                            System.out.println("     |--加速度表采集点个数:" + baseData.mAccCount);
//                            System.out.println("     |--加速度表采集点间隔(毫秒):" + baseData.mAccInterval);
//                            System.out.println("     |--加速度表最大加速度值(mg):" + baseData.mAccMaxValue);
//                        }
//                    }
//
//                    if (carDO != null && obdAnalyse.mPhoneNumber.equals(carDO.getOdbCode())) {
//                        // 作业状态
//                        LambdaQueryWrapper<CarworkDO> lambdaQueryWrapper = Wrappers.lambdaQuery();
//                        lambdaQueryWrapper.gt(CarworkDO::getLocTime, new Date(obdDTO.getLocTime().getTime() - 3600));
//                        lambdaQueryWrapper.eq(CarworkDO::getTerminal, carDO.getWorkTerminal());
//                        List<CarworkDO> carworkDOS = SpringContextHolder.getBean(ICarworkService.class).getBaseMapper().selectList(lambdaQueryWrapper);
//                        if (carworkDOS.size() > 0) {
//                            obdDTO.setIsWork(1);
//                        }
//                        // 数据存入DB
//                        if (ObjectUtil.isNotNull(obdDTO)) {
//                            SpringContextHolder.getBean(ObdService.class).create(obdDTO);
//                            log.info("录入数据==>{}", obdDTO);
//                        }
//                        // 将实时位置信息存入redis 60s过期
//                        if (obdDTO.getMLatitude() != null && obdDTO.getMLongitude() != null) {
//                            redisUtil.set("obd-" + carDO.getCarId(), JSONUtil.toJsonStr(obdDTO), 60);
//                        }
//                        // 油耗异常判定
//                        try {
//                            if (redisUtil.get("obd-" + carDO.getCarId()) != null) {
//                                ObdDocument obdDocument1 = JSONUtil.toBean(redisUtil.get("obd-" + carDO.getCarId()), ObdDocument.class);
//                                //油耗异常判定
//                                if (obdDTO.getMOilConsumptionValue() != null && obdDocument1.getMOilConsumptionValue() != null && (obdDTO.getMOilConsumptionValue() - obdDocument1.getMOilConsumptionValue()) > 1000) {
//                                    OilabnormalDO oilabnormalDO = new OilabnormalDO();
//                                    oilabnormalDO.setCarId(obdDTO.getCarId());
//                                    oilabnormalDO.setDeptId(obdDTO.getDeptId());
//                                    oilabnormalDO.setAbnormalOil(BigDecimal.valueOf(obdDTO.getMOilConsumptionValue() - obdDocument1.getMOilConsumptionValue()));
//                                    oilabnormalDO.setAbnormalTime(obdDTO.getLocTime());
//                                    oilabnormalDO.setAbnormalAddress(GouldUtils.getAMapByLngAndLat(obdDTO.getMLongitude().toString(), obdDTO.getMLatitude().toString()));
//                                    oilabnormalDO.setCarNum(carDO.getCarNum());
//                                    oilabnormalDO.setDeptName(obdDTO.getDeptName());
//                                    oilabnormalDO.setCarTypeName(carTypeDO.getCarTypeName());
//                                    oilabnormalDO.setCarTypeId(carTypeDO.getCarTypeId());
//                                    SpringContextHolder.getBean(IOilabnormalService.class).save(oilabnormalDO);
//                                }
//                            }
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }
//            }
//        }
//
    }

    /**
     * 功能：读取完毕客户端发送过来的数据之后的操作
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("...............数据接收-完毕...............");
        // 第一种方法：写一个空的buf，并刷新写出区域。完成后关闭sock channel连接。
//        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
//        String returnInfo = "服务端已接收数据！";
//        ctx.writeAndFlush(Unpooled.copiedBuffer(returnInfo, CharsetUtil.UTF_8)).addListener(ChannelFutureListener.CLOSE);
    }

    /**
     * 功能：服务端发生异常的操作
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("...............业务处理异常...............");
        log.error("业务处理异常=>{}",cause.getMessage());
        // 删除ObdAnalyse
        obdAnalyseMap.remove(ctx.channel().id());
        ctx.close();
    }

}
